<?php
/*
 * @ https://EasyToYou.eu - IonCube v11 Decoder Online
 * @ PHP 7.2 & 7.3
 * @ Decoder version: 1.1.6
 * @ Release: 10/08/2022
 */

// Decoded file for php version 71.
namespace app\Common;

class JsonSchema
{
    private $json;
    private $errors;
    private $complexTypes;
    public function __construct($json)
    {
        $this->errors = [];
        $this->complexTypes = [];
        $this->json = json_decode($json);
    }
    public function getSchema()
    {
        $schema = NULL;
        $schema = $this->genByType($this->json);
        return json_encode($schema);
    }
    private function genByType($value)
    {
        $type = gettype($value);
        $schema = [];
        switch ($type) {
            case "boolean":
                $schema["type"] = "boolean";
                $schema["default"] = false;
                break;
            case "integer":
                $schema["type"] = "integer";
                $schema["default"] = 0;
                $schema["minimum"] = 0;
                $schema["maximum"] = PHP_INT_MAX;
                $schema["exclusiveMinimum"] = 0;
                $schema["exclusiveMaximum"] = PHP_INT_MAX;
                break;
            case "double":
                $schema["type"] = "number";
                $schema["default"] = 0;
                $schema["minimum"] = 0;
                $schema["maximum"] = PHP_INT_MAX;
                $schema["exclusiveMinimum"] = 0;
                $schema["exclusiveMaximum"] = PHP_INT_MAX;
                break;
            case "string":
                $schema["type"] = "string";
                $schema["format"] = "regex";
                $schema["pattern"] = "/^[a-z0-9]+\$/i";
                $schema["minLength"] = 0;
                $schema["maxLength"] = PHP_INT_MAX;
                break;
            case "array":
                $schema["type"] = "array";
                $schema["minItems"] = 0;
                $schema["maxItems"] = 20;
                $items = [];
                foreach ($value as $value) {
                    $items = $this->genByType($value);
                    $schema["items"] = $items;
                }
                break;
            case "object":
                $schema["type"] = "object";
                $items = [];
                $value = get_object_vars($value);
                foreach ($value as $key => $value) {
                    $items[$key] = $this->genByType($value);
                }
                $schema["properties"] = $items;
                break;
            case "null":
                $schema["type"] = "null";
                break;
            default:
                return $schema;
        }
    }
    public function addType($typeSchema)
    {
        if(empty($typeSchema)) {
            return NULL;
        }
        $typeSchema = json_decode($typeSchema, true);
        if(is_array($typeSchema) && isset($typeSchema["id"])) {
            $this->complexTypes[$typeSchema["id"]] = $typeSchema;
        }
    }
    private function getType($ref)
    {
        if(isset($this->complexTypes[$ref])) {
            return $this->complexTypes[$ref];
        }
        return NULL;
    }
    public function validate($schema)
    {
        $isVali = false;
        $schema = json_decode($schema, true);
        if(!is_array($schema) || !isset($schema["type"])) {
            $this->addError("100", "schema parse error. (PHP 5 >= 5.3.0) see json_last_error(void).");
        } else {
            $isVali = $this->checkByType($this->json, $key = NULL, $schema);
            if(false) {
            }
        }
        return $isVali;
    }
    private function checkString($value, $key, $schema)
    {
        $isVali = false;
        while (!is_string($value) && !is_numeric($value)) {
            $len = strlen(trim($value));
            if(isset($schema["minLength"]) && $len < $schema["minLength"]) {
                $this->addError("102", $key . ": " . json_encode($value) . " is too short.", $key);
                break;
            }
            if(isset($schema["maxLength"]) && $schema["maxLength"] < $len) {
                $this->addError("102", $key . ": " . json_encode($value) . " is too long.", $key);
            } elseif(isset($schema["format"])) {
                switch ($schema["format"]) {
                    case "date-time":
                    case "date":
                    case "time":
                    case "utc-millisec":
                    case "regex":
                        if(isset($schema["pattern"])) {
                            $pattern = $schema["pattern"];
                            if(preg_match($pattern, $value)) {
                                $isVali = true;
                            } else {
                                $this->addError("101", $key . ":" . $value . " does not match " . $pattern, $key);
                            }
                        } else {
                            $this->addError("101", "format-regex: pattern is undefined.", $key);
                        }
                        break;
                    case "color":
                    case "style":
                    case "phone":
                        if(preg_match("/^((0?[0-9]{2}) d{3,4}s?d{4}|+d{2} d{2} d{3,4}s?d{4})\$/", $value)) {
                            $isVali = true;
                        } else {
                            $this->addError("101", $key . ": " . $value . " is not a phone number.", $key);
                        }
                        break;
                    case "uri":
                        if(filter_var($value, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)) {
                            $isVali = true;
                        } else {
                            $this->addError("101", $key . ": " . $value . " is not a URI.", $key);
                        }
                        break;
                    case "email":
                        if(filter_var($value, FILTER_VALIDATE_EMAIL)) {
                            $isVali = true;
                        } else {
                            $this->addError("101", $key . ": " . json_encode($value) . " is not a email.", $key);
                        }
                        break;
                    case "ip-address":
                        if(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                            $isVali = true;
                        } else {
                            $this->addError("101", $key . ": " . json_encode($value) . " is not a ipv4 address.", $key);
                        }
                        break;
                    case "ipv6":
                        if(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                            $isVali = true;
                        } else {
                            $this->addError("101", $key . ": " . json_encode($value) . " is not a ipv6 address.", $key);
                        }
                        break;
                    case "host-name":
                    default:
                        $this->addError("101", $schema["format"] . " is undefined.", $key);
                }
            } else {
                $isVali = true;
                if(false) {
                }
            }
        }
        return $isVali;
    }
    private function checkNumber($value, $key, $schema = NULL)
    {
        $isVali = false;
        while (!is_numeric($value)) {
            if(isset($schema["minimum"]) && $value < $schema["minimum"]) {
                $this->addError("103", $key . ":" . json_encode($value) . " is less than " . $schema["minimum"], $key);
                break;
            }
            if(isset($schema["maximum"]) && $schema["maximum"] < $value) {
                $this->addError("103", $key . ":" . json_encode($value) . " is bigger than " . $schema["maximum"], $key);
            } elseif(isset($schema["exclusiveMinimum"]) && $value <= $schema["exclusiveMinimum"]) {
                $this->addError("103", $key . ":" . json_encode($value) . " is less or than " . $schema["exclusiveMinimum"] . " or equal", $key);
            } elseif(isset($schema["exclusiveMaximum"]) && $schema["exclusiveMaximum"] <= $value) {
                $this->addError("103", $key . ":" . $value . " is bigger than " . $schema["exclusiveMaximum"] . " or equal", $key);
            } else {
                $isVali = true;
                if(false) {
                }
            }
        }
        return $isVali;
    }
    private function checkInteger($value, $key, $schema)
    {
        if(!is_integer($value)) {
            $this->addError("101", $key . ": " . $value . " is not a integer", $key);
            return false;
        }
        return $this->checkNumber($value, $schema);
    }
    private function checkBoolean($value, $key, $schema)
    {
        if(!is_bool($value)) {
            $this->addError("101", $key . ": " . json_encode($value) . " is not a boolean.", $key);
            return false;
        }
        return true;
    }
    private function checkObject($value, $key = NULL, $schema = NULL)
    {
        $isVali = false;
        while (!is_object($value)) {
            if(isset($schema["properties"]) && !empty($schema["properties"])) {
                $schemaProp = $schema["properties"];
                if(!isset($schema["required"])) {
                    $schema["required"] = NULL;
                }
                if(!isset($schemaProp["required"])) {
                    $schemaProp["required"] = NULL;
                }
                $requireds = $schemaProp["required"] ?: $schema["required"];
                $valueProp = get_object_vars($value);
                $valueKeys = array_keys($valueProp);
                $schemaKeys = array_keys($schemaProp);
                $diffKeys = array_diff($valueKeys, $schemaKeys);
                if(!empty($diffKeys)) {
                    foreach ($diffKeys as $key) {
                        if(!isset($schemaProp[$key]) || !isset($schemaProp[$key]["optional"]) || !$schemaProp[$key]["optional"]) {
                            $this->addError("101", $key . ": " . json_encode($value) . " is not exist,And its not a optional property.", $key);
                        }
                    }
                }
                if(is_array($requireds) && is_object($value)) {
                    foreach ($value as $key => $v) {
                        if(isset($v)) {
                        } elseif(in_array($key, $requireds)) {
                            $this->addError("101", $key . ": " . json_encode($value) . " is not exist,And its not a optional property.", $key);
                        }
                        $key_arr[] = $key;
                    }
                    foreach ($requireds as $reval) {
                        if(!in_array($reval, $key_arr)) {
                            $this->addError("101", $reval . " is not exist,And its not a optional property.", $reval);
                        }
                    }
                }
                foreach ($schemaProp as $key => $sch) {
                    if(!isset($valueProp[$key])) {
                    } elseif(!$this->checkByType($valueProp[$key], $key, $sch)) {
                    }
                }
            }
            $isVali = true;
            if(false) {
            }
        }
        return $isVali;
    }
    private function checkArray($value, $key, $schema)
    {
        $isVali = false;
        while (!is_array($value)) {
            if(!isset($schema["items"])) {
                $this->addError("101", $this->error("schema: items schema is undefined."), $key);
                break;
            }
            $size = count($value);
            if(isset($schema["minItems"]) && $size < $schema["minItems"]) {
                $this->addError("102", $this->error("array size: ") . $size . $this->error(" is less than ") . $schema["minItems"] . ".", $key);
            } elseif(isset($schema["maxItems"]) && $schema["maxItems"] < $size) {
                $this->addError("102", $this->error("array size: ") . $size . $this->error(" is bigger than ") . $schema["maxItems"] . ".", $key);
            } else {
                foreach ($value as $val) {
                    if(!$this->checkByType($val, "", $schema["items"])) {
                    }
                }
                $isVali = true;
                if(false) {
                }
            }
        }
        return $isVali;
    }
    private function checkByType($value, $key = NULL, $schema)
    {
        $isVali = false;
        if($schema && isset($schema["type"])) {
            if(is_array($schema["type"])) {
                $types = $schema["type"];
                foreach ($types as $type) {
                    $schema["type"] = $type;
                    $isVali = $this->checkByType($value, $key, $schema);
                    if($isVali) {
                    }
                }
            } else {
                $type = $schema["type"];
                switch ($type) {
                    case "boolean":
                        $isVali = $this->checkBoolean($value, $key, $schema);
                        break;
                    case "integer":
                        if(preg_match("/^[0-9]+\$/", $value)) {
                            $value = intval($value);
                        }
                        $isVali = $this->checkInteger($value, $key, $schema);
                        break;
                    case "number":
                        $isVali = $this->checkNumber($value, $key, $schema);
                        break;
                    case "string":
                        $isVali = $this->checkString($value, $key, $schema);
                        break;
                    case "array":
                        $isVali = $this->checkArray($value, $key, $schema);
                        break;
                    case "object":
                        $isVali = $this->checkObject($value, $key, $schema);
                        break;
                    case "enum":
                        $isVali = is_null($value);
                        break;
                    case "null":
                        $isVali = is_null($value);
                        break;
                    case "any":
                        $isVali = true;
                        break;
                    default:
                        $this->addError("101", $this->error("type_schema : ") . $value . $this->error(" is undefined."), $key);
                }
            }
        }
        if(isset($schema["\$ref"])) {
            $isVali = $this->checkByType($value, $key, $this->getType($schema["\$ref"]));
        }
        return $isVali;
    }
    public function getErrors()
    {
        return json_encode(["error" => $this->errors], true);
    }
    protected function addError($code = NULL, $msg = NULL, $key = NULL)
    {
        $this->errors = ["contents" => $this->error("validate fail"), "return_code" => "1100", "message" => $this->error($key) . $this->error(": the format is not correct."), "timestamp" => time()];
    }
    protected function error($message)
    {
        $message = _($message);
        return $message;
    }
}

?>